PostgreSQL 全文搜索 词典
1 背景知识
词典用于指定包含的 停用词
(stop words
)。并且它能将词进行 正规化 ,正规化后的词能够匹配不同派生形式。一个 正规化
的词被称为一个 词位
,有效提高搜索质量。
正规化
还能减小了文档的 tsvector
大小,因而提高了查询性能。
1.1 正规化的例子
-
自然语言正规化 :Ispell 词典尝试将单词缩减为一种正规化的形式;例如:词典将移除词的前缀和后缀,提取出词根。
-
URL位置正规化:规范化来得到等效的 URL 匹配。
-
颜色名名称正规化:可以使用十六进制数值值替换颜色名称。如下所示:
red, green, blue, magenta -> FF0000, 00FF00, 0000FF, FF00FF
- 数字索引正规化: 保留小数点后两位。例如
3.14_159265359
、3.14_15926
,都将正规化为3.14
。
1.2 词典输入和输出说明
- 输入是非停用词记号,则返回一个词位数组。(因为一个记号可能返回多个词位)。
- 输入
TSL_FILTER
标志被的词位,则用一个新记号
来替换为原始记号(这个字典被称为一个过滤字典
。 )。 - 输入是一个停用词记号,则返回一个空数组。
- 输入无法识别的记号,则返回
NULL
。
1.3 预置词典和自定义词典
-
预定义字典
PostgreSQL数据库为许多语言提供了预定义的字典。 -
自定义词典
也有多种预定义模板可以被用于创建带自定义参数的新词典。每一种预定义词典模板在下面描述。 -
如果没有合适的现有模板,可以创建新的插件;例如 Kingbase 服务器编程 插件。
1.4 文本搜索配置与词典的关系
一个文本搜索配置 把一个解析器 和的词典 绑定在一起。对于解析器返回的记号类型,文本搜索配置 都指定了对应的词典。
当一个 词位
被词典 找到时,词典将其识别为一个已知词。当它被标识为一个 停用词
时,它将被丢弃并且不会被索引和用于搜索。
当一个词位被找到后,后续同样的词位将会直接替换加快查找速度。
2 Stop word (停用词 )
在每一段英语文本都包含 a
和 the
单词,因此把它们存储在一个索引中是没有用处的。但是,停用词确实会影响在 tsvector
中的位置,这进而会影响排名:
2.1 停用词的输出形式
SELECT to_tsvector('english', 'in the list of stop words');
//屏幕输出:
to_tsvector
----------------------------
'list':3 'stop':5 'word':6
由于停用词关系,位置 1、2、4
返回为空。
2.2 停用词对排名计算的影响
对于文档的排名计算 ,停用词影响 相似度
,请看以下两个例子:
- 停用词较多时,
相似度
较低。
SELECT ts_rank_cd (to_tsvector('english', 'in the list of stop words'), to_tsquery('list & stop'));
ts_rank_cd
------------
0.05
(1 row)
- 停用词较少时,
相似度
较高。
postgres=# SELECT ts_rank_cd (to_tsvector('english', 'list stop words'), to_tsquery('list & stop'));
ts_rank_cd
------------
0.1
(1 row)
3 simple 词典
simple
词典:跟其他词典相似。将 记号
转换为小写形式并检查 停用词
文件。如果该 记号
在 停用词
文件中被找到,则返回一个空数组,丢弃记号。否则,该词的小写形式被返回作为正规化的词位。
如果 标记
报告为未识别的情况,将 标记
传递给列表中的下一个词典继续判断。
3.1 创建自定义词典
使用 simple
模板的自定义词典的例子,创建public.simple_dict 词典。
CREATE TEXT SEARCH DICTIONARY public.simple_dict (
TEMPLATE = pg_catalog.simple,
STOPWORDS = english
);
-
TEMPLATE
pg_catalog.simple 是一个词典。可以使用\dFd
查看。 -
STOPWORDS :
english是一个停用词
文件的基本名称。该文件的全名将是$SHAREDIR/tsearch_data/english.stop
,其中$SHAREDIR
表示PostgreSQL安装的共享数据目录,通常是/usr/local/share/postgresql
(可以使用pg_config --sharedir
查确定)。
文件格式:词的列表,每行一个。空行和尾部的空格都被忽略,并且大写也被折叠成小写,但是没有其他对该文件内容的处理。
3.2 测试自定义词典
YeS
不是停用词,所以返回词位的小写形式yes
。
SELECT ts_lexize('public.simple_dict', 'YeS');
//屏幕输出:
ts_lexize
-----------
{yes}
The
则是停用词,所以返回NULL。
SELECT ts_lexize('public.simple_dict', 'The');
//屏幕输出:
ts_lexize
-----------
{}
- 找不到停用词( Accept = false)则返回
当Accept = false
时, 如果在停用词文件中找不到对应单词,则则返回NULL 。
ALTER TEXT SEARCH DICTIONARY public.simple_dict ( Accept = false );
ALTER TEXT SEARCH DICTIONARY
\dFd+ public.simple_dict
List of text search dictionaries
Schema | Name | Template | Init options | Description
--------+-------------+-------------------+-----------------------------------------+-------------
public | simple_dict | pg_catalog.simple | stopwords = 'english', accept = 'false' |
(1 row)
SELECT ts_lexize('public.simple_dict', 'YeS');
ts_lexize
-----------
(1 row)
SELECT ts_lexize('public.simple_dict', 'The');
ts_lexize
-----------
{}
(1 row)
停用词文件必须使用 UTF-8
编码存储。
由于会话连接时会读取一次词典配置,如果想要修改后的词典生效,请使用 ALTER TEXT SEARCH DICTIONARY
命令。
4 Synonym 词典
同义词词典可以解决英语的同义词问题。例如,可以防止 Paris
(巴黎) 单词正规化为 pari
(相同),这样会造成匹配的时候搜索范围的扩大,搜索不准确。可以创建一个自定义的同义词词典,从而避免这个问题。
4.1 创建同义词词典
Paris
解析为pari
。
SELECT * FROM ts_debug('english', 'Paris');
alias | description | token | dictionaries | dictionary | lexemes
-----------+-----------------+-------+----------------+--------------+---------
asciiword | Word, all ASCII | Paris | {english_stem} | english_stem | {pari}
- 创建同义词词典文件
SYNONYMS 模版文件格式:每对同义词放置在同一行,单词后面跟上同义词,用空格分隔。
vi $PGHOME/share/tsearch_data/my_synonyms.syn
Paris paris
- 创建同义词词典。
参数 | 说明 |
---|---|
my_synonym | 自定义同义词词典的名称。 |
TEMPLATE | 以默认的同义词词典作为模版,创建新的同义词词典。 |
SYNONYMS | 同义词词典的模版文件,默认在 $SHAREDIR/tsearch_data/my_synonyms.syn 目录下。 |
CREATE TEXT SEARCH DICTIONARY my_synonym (
TEMPLATE = synonym,
SYNONYMS = my_synonyms
);
//屏幕输出:
CREATE TEXT SEARCH DICTIONARY
4.2 修改文本搜索配置
修改预定义配置,将 my_synonyms
词典放在 english_stem
词典之前。
ALTER TEXT SEARCH CONFIGURATION english
ALTER MAPPING FOR asciiword
WITH my_synonym, english_stem;
ALTER TEXT SEARCH CONFIGURATION
- 验证同义词问题已解决。
SELECT * FROM ts_debug('english', 'Paris');
//屏幕输出:
alias | description | token | dictionaries | dictionary | lexemes
-----------+-----------------+-------+---------------------------+------------+---------
asciiword | Word, all ASCII | Paris | {my_synonym,english_stem} | my_synonym | {paris}
(1 row)
4.3 同义词模版详解
*
星号可以放在配置文件同义词的末尾。表示该同义词是一个前缀。
- 当使用
to_tsvector()
函数时,*
星号将被忽略。 - 当使用
to_tsquery()
函数时,将产生带有匹配前缀的查询项。
下面是$SHAREDIR/tsearch_data/synonym_sample.syn
默认模版的内容。
postgres pgsql
postgresql pgsql
postgre pgsql
gogle googl
indices index*
- 可以得出以下结果。
CREATE TEXT SEARCH DICTIONARY syn (template=synonym, synonyms='synonym_sample');
SELECT ts_lexize('syn', 'indices');
//屏幕输出:
ts_lexize
-----------
{index}
(1 row)
CREATE TEXT SEARCH CONFIGURATION tst (copy=simple);
ALTER TEXT SEARCH CONFIGURATION tst ALTER MAPPING FOR asciiword WITH syn;
SELECT to_tsvector('tst', 'indices');
to_tsvector
-------------
'index':1
(1 row)
SELECT to_tsquery('tst', 'indices');
//屏幕输出:
to_tsquery
------------
'index':*
(1 row)
SELECT 'indexes are very useful'::tsvector;
//屏幕输出:
tsvector
---------------------------------
'are' 'indexes' 'useful' 'very'
(1 row)
SELECT 'indexes are very useful'::tsvector @@ to_tsquery('tst', 'indices');
//屏幕输出:
?column?
----------
t
(1 row)
5 Thesaurus 词典
Thesaurus
词典,也称分类词典。但是和 Synonym 词典 不同,Thesaurus 词典 能够匹配短语句。
短语
5.1 短语匹配原则
分类词典会用一个 首选词
替换所有 非首选词
,并且也可选择地保留原始术语用于索引。
分类词典的当前实现是 Synonym 词典 的一个扩展,并增加了 短语
支持。分类词典的配置文件格式如下:
# this is a comment
sample word(s) : indexed word(s)
more sample word(s) : more indexed word(s)
...
:
(冒号)前面是 非首选词
,后面是 首选词
。
5.2 子词典
一个分类词典使用一个 子词典
、用于 正规化 输入文本。
由于 子词典
不能指定自定义停用词;但可以使用逻辑判断符号 ?
代替 停用词
。例如,子词典 a
和 the
是停用词:
? one ? two : swsw
a one the two
或者 the one a two
都会被 swsw
替换。
注意:在索引中使用分类词典时,当分类词典的参数发生变化时,都需要强制重建索引。
5.3 创建分类词典
- 创建分类词典文件。
vi $PGHOME/share/tsearch_data/mythesaurus.ths
one two three : *123
one two : *12
one : *1
two : *2
supernovae stars : *sn
supernovae : *sn
booking tickets : order invitation cards
booking ? tickets : order invitation Cards
- 创建分类词典。
CREATE TEXT SEARCH DICTIONARY thesaurus_simple (
TEMPLATE = thesaurus,
DictFile = mythesaurus,
Dictionary = pg_catalog.english_stem
);
参数 | 说明 |
---|---|
thesaurus_simple | 自定义分类词典的名称。 |
TEMPLATE=thesaurus | 分类词典的模版,请使用 \dFt命令查看。 |
Dictionary | 分类词典的所使用的 子词典 、请使用 \dFd命令查看。 |
DictFile = mythesaurus | 分类词典的词典文件,请在 $PGHOME/share/tsearch_data/ 文件创建。 |
5.4 修改文本搜索配置
ALTER TEXT SEARCH CONFIGURATION russian
ALTER MAPPING FOR asciiword, asciihword, hword_asciipart
WITH thesaurus_simple;
6 Thesaurus 词典配置
6.1 词典设计
- 准备一个天文学词库
thesaurus_astro
,其中包含一些天文词汇。
vi $PGHOME/share/tsearch_data/thesaurus_astro.ths
supernovae stars : sn
crab nebulae : crab
6.2 创建天文学词典
CREATE TEXT SEARCH DICTIONARY thesaurus_astro (
TEMPLATE = thesaurus,
DictFile = thesaurus_astro,
Dictionary = english_stem
);
6.3 修改预定义配置
ALTER TEXT SEARCH CONFIGURATION russian
ALTER MAPPING FOR asciiword, asciihword, hword_asciipart
WITH thesaurus_astro, english_stem;
6.4 检查词典是否配置正确
6.4.1 验证 tsquery
SELECT plainto_tsquery('russian','supernova star');
plainto_tsquery
-----------------
'sn'
(1 row)
6.4.2 验证 tsvector
SELECT to_tsvector('russian','supernova star');
to_tsvector
-------------
'sn':1
(1 row)
7 Ispell 词典
8 参考链接
Thesaurus Dictionary
词典、Ispell Dictionary
词典、Snowball Dictionary
词典。请参考 PostgreSQL 官方文档。